package com.sale.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sale.common.core.exception.GlobalException;
import com.sale.common.core.utils.StringUtils;
import com.sale.common.dict.utils.DictUtils;
import com.sale.common.mybatis.core.page.PageQuery;
import com.sale.common.mybatis.core.page.TableDataInfo;
import com.sale.common.satoken.utils.LoginHelper;
import com.sale.system.api.RemoteUnitService;
import com.sale.system.api.domain.SysDictData;
import com.sale.system.api.domain.dto.MaterialAuxiliaryDto;
import com.sale.system.api.model.MaterialUnitDto;
import com.sale.system.domain.*;
import com.sale.system.domain.dto.MaterialRawDto;
import com.sale.system.domain.dto.ProjectRecursionDto;
import com.sale.system.domain.dto.SysCategoryDto;
import com.sale.system.domain.dto.SysTheDropDto;
import com.sale.system.domain.vo.MaterialAlarmVo;
import com.sale.system.domain.vo.MaterialMqMessageVo;
import com.sale.system.domain.vo.MaterialRawVo;
import com.sale.system.mapper.*;
import com.sale.system.service.*;
import com.sale.system.util.MaterialMqUtil;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description 原料信息
 * @Date 23-07-13
 * @Author hl
 **/
@RequiredArgsConstructor
@Service
public class MaterialRawServiceImpl implements IMaterialRawService {

    private final MaterialRawMapper materialRawMapper;

    private final SysMaterialCodingMapper sysMaterialCodingMapper;

    private final ISysMidSplitService sysMidSplitService;

    private final MaterialFinishedServiceImpl materialFinishedService;

    private final MaterialAuxiliaryMapper materialAuxiliaryMapper;

    private final ISysDocumentService sysDocumentService;

    private final SysAuxiliaryUnitDetailMapper sysAuxiliaryUnitDetailMapper;

    private final SysTheAlarmMapper sysTheAlarmMapper;

    private final ISysCategoryService sysCategoryService;


    /**
     * 分页查询原料信息
     *
     * @param materialRaw 原料信息,pageQuery 分页参数
     * @return TableDataInfo<MaterialRaw>
     */
    @Override
    public TableDataInfo<MaterialRawDto> selectRawList(MaterialRawVo materialRaw, PageQuery pageQuery) {
        Page<MaterialRawDto> page = materialRawMapper.selectRawList(pageQuery.build(), this.buildQueryWrapper(materialRaw));
        //渲染辅助属性
        List<MaterialRawDto> list = page.getRecords();
//        // 多单位
//        List<SysTheDropDto> listThe= sysAuxiliaryUnitMapper.selectMultiMeteringUnitAllList();
//        Map<String,String> map = listThe.stream()
//            .collect(Collectors.toMap(SysTheDropDto::getValue,SysTheDropDto::getLabel));
        //单位集合

        for (MaterialRawDto dto :
            list) {
            // String unit = dto.getMaterialUnit();
            //if (unit != null) {
            //  dto.setMaterialUnitDict(unitByCodeToMap.get(unit).getUnitName());
            // }
            dto.setAuxiliaryAttribute(materialAuxiliaryMapper.selectAuxiliaryById(dto.getMaterialId()));
            //类别
            dto.setMaterialCategory("1");
            dto.setMaterialCategoryDict("原料");
        }
        return TableDataInfo.build(page);
    }

    private Wrapper<MaterialRawVo> buildQueryWrapper(MaterialRawVo materialRaw) {
        Map<String, Object> params = materialRaw.getParams();
        QueryWrapper<MaterialRawVo> wrapper = Wrappers.query();
        wrapper
            .like(ObjectUtil.isNotNull(materialRaw.getMaterialCode()), "t1.material_code", materialRaw.getMaterialCode())
            .like(StringUtils.isNotBlank(materialRaw.getMaterialName()), "t1.material_name", materialRaw.getMaterialName())
            .eq(StringUtils.isNotBlank(materialRaw.getMaterialType()), "t1.material_type", materialRaw.getMaterialType())
            .eq(StringUtils.isNotBlank(materialRaw.getMaterialStatus()), "t1.material_status", materialRaw.getMaterialStatus())
            .eq(StringUtils.isNotBlank(materialRaw.getMaterialTypeName()), "t1.material_type", materialRaw.getMaterialTypeName()).between(params.get("beginTime") != null && params.get("endTime") != null,
                "t1.create_time", params.get("beginTime"), params.get("endTime"));
        return wrapper;
    }

    /**
     * 新增原料信息
     *
     * @param materialRaw 原料id
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertRaw(MaterialRawVo materialRaw) throws Exception {
        MaterialRaw raw = new MaterialRaw();
        BeanUtils.copyProperties(materialRaw, raw);
        raw.setMaterialId(IdWorker.getId());
        raw.setCreateBy(LoginHelper.getUsername());
        List<SysAuxiliaryUnitDetail> list2 = materialRaw.getList();
        StringBuffer moreUnit = new StringBuffer();
        for (SysAuxiliaryUnitDetail item : list2) {
            moreUnit.append(item.getAuxiliaryId()).append(",");
            item.setMaterialId(raw.getMaterialId());
        }
        raw.setMaterialMoreUnit(moreUnit.toString().substring(0, moreUnit.length() - 1));
        //原料编码按照类别配置中得生成
        SysCategoryDto sysCategoryDto = sysCategoryService.selectCategoryById(Long.parseLong(materialRaw.getMaterialType()));
        String s = sysMidSplitService.selectSplitStr(sysCategoryDto.getCodeRule());
        if (StringUtils.isEmpty(s)) {
            throw new GlobalException("编码生成失败，请检查配置");
        }
        raw.setMaterialCode(s);
        int os = materialRawMapper.insert(raw);
        if (os > 0) {
            if (materialRaw.getAlarmCode() != null) {
                List<SysTheAlarm> list = alarmConfiguration(materialRaw.getAlarmCode());
                if (list.size() > 0) {
                    long op = raw.getMaterialId();
                    String materialCode = raw.getMaterialCode();
                    for (SysTheAlarm sysTheAlarm :
                        list) {

                        String roles = "";
                        for (int i = 0; i < sysTheAlarm.getRoleIds().size(); i++) {

                            roles = roles + sysTheAlarm.getRoleIds().get(i);
                            if (sysTheAlarm.getRoleIds().size() - 1 != i) {
                                roles = roles + ",";
                            }

                        }

                        sysTheAlarm.setAlarmRoleId(roles);
                        sysTheAlarm.setAlarmMaterialCode(materialCode);
                        sysTheAlarm.setAlarmAssociatedId(op);
                        sysTheAlarm.setAlarmOfMaterial(1);
                    }
                    if (list.size() != 0) {
                        os = sysTheAlarmMapper.insertSysTheAlarm(list);
                    }
                    if (os == 0) {
                        throw new SQLException("抛出异常");
                    }
                }
            }
        }
        //mq发送消息
        String userIdStr = LoginHelper.getUserIdStr();
        MaterialMqMessageVo materialMqVo = new MaterialMqMessageVo();
        BeanUtils.copyProperties(raw, materialMqVo);
        materialMqVo.setUserIdStr(userIdStr);
        materialMqVo.setMaterialType(Long.parseLong(raw.getMaterialType()));
        materialMqVo.setMaxInventory(String.valueOf(raw.getMaxInventory()));
        MaterialMqUtil.materialMqSend(materialMqVo);

        List<MaterialAuxiliary> list = materialRaw.getAuxiliaryAttribute();
        //当辅助属性不为空时进行新增
        if (list != null) {
            long materialId = raw.getMaterialId();
            for (MaterialAuxiliary auxiliary : list) {
                auxiliary.setMaterialId(materialId);
                auxiliary.setAuxiliaryId(IdWorker.getId());
            }
            //批量新增物料属性信息
            materialAuxiliaryMapper.insertBatch(list);
        }
        if (list2.get(0).getAuxiliaryId() != null) {
            sysAuxiliaryUnitDetailMapper.insertBatch(list2);
        }

        return os;
    }

    /**
     * 删除原料信息
     *
     * @param materialId 原料id
     * @return int
     */
    @Override
    public int deleteRawById(String materialId) throws Exception {
        String[] materialIdS = materialId.split(",");
        ArrayList<String> list = new ArrayList<>();
        for (String str :
            materialIdS) {
            list.add(str);
            MaterialRawDto dto = materialRawMapper.selectRawById(Long.parseLong(str));
            //删除对应属性
            HashMap<String, Object> map = new HashMap<>();
            map.put("material_id", str);
            materialAuxiliaryMapper.deleteByMap(map);
            sysAuxiliaryUnitDetailMapper.deleteByMap(map);
        }
        //mq发送消息(删除)
        MaterialMqMessageVo materialMqVo = new MaterialMqMessageVo();
        materialMqVo.setIdStr(materialId);
        MaterialMqUtil.materialMqSendDelete(materialMqVo);
        return materialRawMapper.deleteBatchIds(list);
    }

    /**
     * 查询单个原料信息
     *
     * @param materialId 原料信息
     * @return MaterialRaw
     */
    @Override
    public MaterialRawDto selectRawById(long materialId) {
        MaterialRawDto dto = materialRawMapper.selectRawById(materialId);
        List<MaterialAuxiliaryDto> list = materialAuxiliaryMapper.selectAuxiliaryById(materialId);
        // List<String> ayList = new ArrayList<>();
        // String[] ars = dto.getMaterialMoreUnit().split(",");
        //ayList.add(dto.getMaterialMoreUnit());
        // System.out.println(Arrays.asList(ars));
        Map<String, Object> map = new HashMap<>();
        map.put("material_id", materialId);
        List<SysAuxiliaryUnitDetail> list1 = sysAuxiliaryUnitDetailMapper.selectByMap(map);
        int alarmOfMaterial = 1;
        List<SysTheAlarm> theList = sysTheAlarmMapper.selectSysTheAlarmList(materialId, alarmOfMaterial);
        MaterialAlarmVo materialAlarmVo = alarmConfigtType(theList);
        dto.setAlarmCode(materialAlarmVo);

        dto.setAuxiliaryAttribute(list);
        dto.setList(list1);
        return dto;
    }

    /**
     * 修改原料信息
     *
     * @param materialRaw 原料信息
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateRawEdit(MaterialRawVo materialRaw) throws Exception {
        MaterialRaw materialRaw1 = materialRawMapper.selectById(materialRaw.getMaterialId());
        List<SysAuxiliaryUnitDetail> list2 = materialRaw.getList();
        StringBuffer moreUnit = new StringBuffer();
        for (SysAuxiliaryUnitDetail item : list2) {
            moreUnit.append(item.getAuxiliaryId()).append(",");
            item.setMaterialId(materialRaw.getMaterialId());
        }
        materialRaw1.setMaterialName(materialRaw.getMaterialName())
            .setMaterialHair(materialRaw.getMaterialHair())
            .setMaterialClosed(materialRaw.getMaterialClosed())
            .setMaterialType(materialRaw.getMaterialType())
            .setMaterialSpec(materialRaw.getMaterialSpec())
            .setMaterialPlace(materialRaw.getMaterialPlace())
            .setSupplierName(materialRaw.getSupplierName())
            .setPurchasePrice(materialRaw.getPurchasePrice())
            .setForewarning(materialRaw.getForewarning())
            .setMinInventory(materialRaw.getMinInventory())
            .setMaxInventory(materialRaw.getMaxInventory())
            .setSpecType(materialRaw.getSpecType())
            //.setMaterialMoreUnit(moreUnit.toString().substring(0,moreUnit.length()-1))
            .setRemark(materialRaw.getRemark());
        int os = materialRawMapper.updateById(materialRaw1);
        //修改告警信息数据
        long sy = materialRaw.getMaterialId();
        String materialCode = materialRaw.getMaterialCode();
        sysTheAlarmMapper.deleteSysTheAlarmOnById(sy);
        if (os > 0) {
            List<SysTheAlarm> list = alarmConfiguration(materialRaw.getAlarmCode());
            for (SysTheAlarm sysTheAlarm : list) {
                String roles = "";
                for (int i = 0; i < sysTheAlarm.getRoleIds().size(); i++) {

                    roles = roles + sysTheAlarm.getRoleIds().get(i);

                    if (i != sysTheAlarm.getRoleIds().size() - 1) {
                        roles = roles + ",";
                    }
                }
                sysTheAlarm.setAlarmRoleId(roles);
                sysTheAlarm.setAlarmAssociatedId(sy);
                sysTheAlarm.setAlarmOfMaterial(1);
                sysTheAlarm.setAlarmMaterialCode(materialCode);
            }
            if (list.size() != 0) {
                os = sysTheAlarmMapper.insertSysTheAlarm(list);
            }
            if (os == 0) {
                throw new SQLException("抛出异常");
            }
        } else {
            throw new SQLException("抛出异常");
        }
        //mq发送消息
        String userIdStr = LoginHelper.getUserIdStr();
        MaterialMqMessageVo materialMqVo = new MaterialMqMessageVo();
        BeanUtils.copyProperties(materialRaw1, materialMqVo);
        materialMqVo.setUserIdStr(userIdStr);
        materialMqVo.setMaterialId(materialRaw1.getMaterialId());
        materialMqVo.setMaterialType(Long.parseLong(materialRaw1.getMaterialType()));
        materialMqVo.setMaxInventory(String.valueOf(materialRaw1.getMaxInventory()));
        MaterialMqUtil.materialMqSend(materialMqVo);

        List<MaterialAuxiliary> list = materialRaw.getAuxiliaryAttribute();
        if (list != null) {
            //删除对应属性
            HashMap<String, Object> map = new HashMap<>();
            long materialId = materialRaw1.getMaterialId();
            map.put("material_id", materialId);
            materialAuxiliaryMapper.deleteByMap(map);
            sysAuxiliaryUnitDetailMapper.deleteByMap(map);
            //重新新增对应属性
            for (MaterialAuxiliary auxiliary :
                list) {
                auxiliary.setMaterialId(materialId);
            }
            //批量新增物料属性信息
            materialAuxiliaryMapper.insertBatch(list);
        }
        if (list2.size() == 0 || list2.get(0).getAuxiliaryUnitId() != null) {
            sysAuxiliaryUnitDetailMapper.insertBatch(list2);
        }


        return os;
    }

    /**
     * 树结构展示
     *
     * @param
     * @return 原料信息集合
     */
    @Override
    public List<ProjectRecursionDto> selectChildrenRawThe() {
        return materialFinishedService.buildMenuTree(materialRawMapper.selectChildrenRawThe());
    }

    /**
     * 根据物料编码获取原料详情
     *
     * @param materialCode
     * @return
     */
    @Override
    public MaterialRawDto getByMaterialCode(String materialCode) {
        // 根据物料编码查询原料详情
        return materialRawMapper.selectDataByCode(materialCode);
    }

    /**
     * 根据原料编码查询类型
     *
     * @param codingId
     * @return
     */
    @Override
    public SysMaterialCoding selectCodingRulesById(String codingId) {
        SysMaterialCoding materialCoding = sysMaterialCodingMapper.selectCodingRulesById(codingId);
        return materialCoding;
    }

    /**
     * 原料冻结
     */
    @Override
    public int updateEditFreeze(Long materialId) {
        MaterialRaw raw = new MaterialRaw();
        raw.setMaterialStatus(1);
        raw.setMaterialId(materialId);
        return materialRawMapper.updateById(raw);
    }

    /**
     * 原料解结
     */
    @Override
    public int updateEditThaw(Long materialId) {
        MaterialRaw raw = new MaterialRaw();
        raw.setMaterialStatus(2);
        raw.setMaterialId(materialId);
        return materialRawMapper.updateById(raw);
    }

    /**
     * 封装告警配置json转集合
     *
     * @param json json数据
     * @return list
     */
    public List<SysTheAlarm> alarmConfiguration(JSONObject json) {
        List<SysTheAlarm> list = new ArrayList<SysTheAlarm>();
        List<SysTheAlarm> list2 = new ArrayList<SysTheAlarm>();
        List<SysTheAlarm> list3 = new ArrayList<SysTheAlarm>();
        JSONArray arr = json.getJSONArray("minSafety");
        JSONArray arr2 = json.getJSONArray("shelfLife");
        JSONArray arr3 = json.getJSONArray("theRe");
        list = JSONArray.parseArray(arr.toJSONString(), SysTheAlarm.class);
        list2 = JSONArray.parseArray(arr2.toJSONString(), SysTheAlarm.class);
        list3 = JSONArray.parseArray(arr3.toJSONString(), SysTheAlarm.class);
        list.addAll(list2);
        list.addAll(list3);
        return list;
    }

    /**
     * 封装返回告警配置
     *
     * @param List 集合
     * @return list
     */
    public MaterialAlarmVo alarmConfigtType(List<SysTheAlarm> List) {
        List<SysDictData> dictList = DictUtils.getDictCache("sys_alarm_mode");
        List<SysDictData> dictList2 = DictUtils.getDictCache("sys_alarm_unit");
        List<SysDictData> dictList3 = DictUtils.getDictCache("sys_alarm_nexus");
        MaterialAlarmVo materialAlarmVo = new MaterialAlarmVo();
        List<SysTheAlarm> list1 = new ArrayList<SysTheAlarm>();
        List<SysTheAlarm> list2 = new ArrayList<SysTheAlarm>();
        List<SysTheAlarm> list3 = new ArrayList<SysTheAlarm>();
        for (SysTheAlarm vo :
            List) {
            for (SysDictData sysData :
                dictList) {
                if (String.valueOf(vo.getAlarmWay()).equals(sysData.getDictValue())) {
                    vo.setAlarmWayDict(sysData.getDictLabel());
                    break;
                }
            }
            for (SysDictData sysData2 :
                dictList2) {
                if (String.valueOf(vo.getAlarmUnit()).equals(sysData2.getDictValue())) {
                    vo.setAlarmUnitDict(sysData2.getDictLabel());
                    break;
                }
            }
            for (SysDictData sysData3 :
                dictList3) {
                if (String.valueOf(vo.getAlarmNexus()).equals(sysData3.getDictValue())) {
                    vo.setAlarmNexusDict(sysData3.getDictLabel());
                    break;
                }
            }
            if (vo.getAlarmRoleId() != null && !"".equals(vo.getAlarmRoleId())) {
                List<String> list = Arrays.asList(vo.getAlarmRoleId().split(","));


                List<Long> str2 = new ArrayList<>();

                for (int i = 0; i < list.size(); i++) {
                    str2.add(Long.valueOf(list.get(i)));
                }


                vo.setRoleIds(str2);
            }


            int type = vo.getAlarmType();
            if (type == 1) {//最小安全库存告警
                list1.add(vo);
            } else if (type == 2) {//保质期告警
                list2.add(vo);
            } else {//复检日期告警
                list3.add(vo);
            }
        }
        materialAlarmVo.setMinSafety(list1);
        materialAlarmVo.setShelfLife(list2);
        materialAlarmVo.setTheRe(list3);
        return materialAlarmVo;
    }
}
